package com.uduemc.biso.node.web.service.html.impl;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.uduemc.biso.core.extities.center.SysComponentType;
import com.uduemc.biso.core.extities.center.SysContainerType;
import com.uduemc.biso.node.core.common.entities.SiteComponent;
import com.uduemc.biso.node.core.common.entities.SiteContainer;
import com.uduemc.biso.node.core.common.entities.SitePage;
import com.uduemc.biso.node.core.entities.*;
import com.uduemc.biso.node.web.component.HIComponentUdinComponent;
import com.uduemc.biso.node.web.component.HIContainerUdinComponent;
import com.uduemc.biso.node.web.component.RequestHolder;
import com.uduemc.biso.node.web.component.html.inter.HIComponentUdin;
import com.uduemc.biso.node.web.component.html.inter.HIContainerUdin;
import com.uduemc.biso.node.web.component.html.inter.HISystemComponentUdin;
import com.uduemc.biso.node.web.exception.NotFound404Exception;
import com.uduemc.biso.node.web.service.ContentService;
import com.uduemc.biso.node.web.service.SRHeadService;
import com.uduemc.biso.node.web.service.byfeign.*;
import com.uduemc.biso.node.web.service.html.BasicUdinService;
import com.uduemc.biso.node.web.service.html.HFormService;
import com.uduemc.biso.node.web.service.html.HSpublicService;
import com.uduemc.biso.node.web.service.html.HSystemItemService;
import com.uduemc.biso.node.web.utils.AssetsResponseUtil;
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@Service
public class HSpublicServiceImpl implements BasicUdinService, HSpublicService {

    @Autowired
    private RequestHolder requestHolder;

    @Autowired
    private ComponentService componentServiceImpl;

    @Autowired
    private SysStaticDataService sysStaticDataServiceImpl;

    @Autowired
    private HIContainerUdinComponent hIContainerUdinComponent;

    @Autowired
    private HIComponentUdinComponent hIComponentUdinComponent;

    @Autowired
    private PageService pageServiceImpl;

    @Autowired
    private SystemService systemServiceImpl;

    @Autowired
    private ContentService contentServiceImpl;

    @Autowired
    private ContainerService containerServiceImpl;

    @Autowired
    private CategoryService categoryServiceImpl;

    @Autowired
    private HSystemItemService hSystemItemServiceImpl;

    @Autowired
    private HFormService hFormServiceImpl;

    @Autowired
    private SRHeadService sRHeadServiceImpl;

    @Override
    public StringBuilder html() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException, NotFound404Exception {
        // 获取当前页面的所有容器数据以及组件数据
        long hostId = requestHolder.getHostId();
        long siteId = requestHolder.getSiteId();
        long pageId = requestHolder.getPageId();

        SitePage sitePage = requestHolder.getAccessPage().getSitePage();
        String type = sitePage.getType();
        if (type.equals("custom")) {
            return html(hostId, siteId, pageId);
        } else if (type.equals("item")) {
            return hSystemItemServiceImpl.html();
        } else {
            throw new NotFound404Exception("未能通过type类型，找到对应的调用方法！ type: " + type);
        }
    }

    @Override
    public StringBuilder html(long hostId, long siteId, long pageId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        List<SiteContainer> listSiteContainer = containerServiceImpl.getInfosByHostSitePageIdAndArea(hostId, siteId, pageId, (short) 0);
        if (CollectionUtils.isEmpty(listSiteContainer)) {
            return new StringBuilder("<!-- spublic empty -->");
        }
        List<SiteContainerParentData> listSiteContainerParentData = SiteContainerParentData.getListSiteContainerParentData(listSiteContainer);
        List<SiteComponent> listSiteComponent = componentServiceImpl.getInfosByHostSitePageIdAndArea(hostId, siteId, pageId, (short) 0);

        // 过滤富文本中的内容
        if (!CollectionUtils.isEmpty(listSiteComponent)) {
            for (SiteComponent siteComponent : listSiteComponent) {
                SComponent component = siteComponent.getComponent();
                String content = component.getContent();
                component.setContent(contentServiceImpl.filterUEditorContentWithSite(content));
            }
        }

        // 容器引用表单数据获取
        List<SContainerQuoteForm> listSContainerQuoteForm = containerServiceImpl.getSContainerQuoteFormOkByHostSiteId(hostId, siteId);

        StringBuilder stringBuilder = new StringBuilder("<!-- spublic -->\n");

        List<StringBuilder> makeHtml = makeHtml(listSiteContainerParentData, listSiteComponent, listSContainerQuoteForm, 0L);

        if (!CollectionUtils.isEmpty(makeHtml)) {
            makeHtml.forEach(stringBuilder::append);
        }

        return AssetsResponseUtil.htmlCompress(stringBuilder);
    }

    /**
     * 通过参数 listSiteContainerParentData 开始进行循环， 当 遇到 SiteContainer 下有 SiteComponent
     * 数据的时候进行 SiteComponent 渲染， 当 遇到 SiteContainer 下有 SContainerQuoteForm 数据的时候进行
     * Form 表单渲染，
     *
     * @param listSiteContainerParentData
     * @param listSiteComponent
     * @param listSContainerQuoteForm
     * @param parentId
     * @return
     * @throws JsonParseException
     * @throws JsonMappingException
     * @throws JsonProcessingException
     * @throws IOException
     */
    private List<StringBuilder> makeHtml(List<SiteContainerParentData> listSiteContainerParentData, List<SiteComponent> listSiteComponent,
                                         List<SContainerQuoteForm> listSContainerQuoteForm, long parentId)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        List<SiteContainer> listSiteContainer = getChildrenData(listSiteContainerParentData, parentId);
        if (CollectionUtils.isEmpty(listSiteContainer)) {
            return emptyListSiteContainer(parentId, listSiteContainerParentData, listSiteComponent, listSContainerQuoteForm);
        }

        List<StringBuilder> arrayList = new ArrayList<StringBuilder>();
        listSiteContainer.forEach(item -> {
            StringBuilder stringBuilder = new StringBuilder();
            Long id = item.getSContainer().getId();
            // 子节点的所有渲染html内容
            List<StringBuilder> makeHtml = null;
            try {
                makeHtml = makeHtml(listSiteContainerParentData, listSiteComponent, listSContainerQuoteForm, id);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            SContainer sContainer = item.getSContainer();
            Long typeId = sContainer.getTypeId();
            SysContainerType sysContainerType = null;
            try {
                sysContainerType = sysStaticDataServiceImpl.getContainerTypeInfoById(typeId);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (sysContainerType != null) {
                HIContainerUdin containerUdin = hIContainerUdinComponent.getHIContainerUdinByName(sysContainerType.getType());
                if (containerUdin != null) {
                    StringBuilder html = containerUdin.html(item, makeHtml);
                    stringBuilder.append(html);
                }
            }
            arrayList.add(stringBuilder);
        });

        return arrayList;
    }

    /**
     * 通过 parentId 找到对应的子项容器数据为空时存在的情况！包含 component 展示组件数据，包含 容器引用表单
     * 数据，什么都没有。通过这三种情况分别进行处理获取到 containerBox 下的 HTML部分 然后进行返回
     *
     * @param parentId
     * @param listSiteContainerParentData
     * @param listSiteComponent
     * @param listSContainerQuoteForm
     * @return
     * @throws IOException
     * @throws JsonProcessingException
     * @throws JsonMappingException
     * @throws JsonParseException
     */
    private List<StringBuilder> emptyListSiteContainer(long parentId, List<SiteContainerParentData> listSiteContainerParentData,
                                                       List<SiteComponent> listSiteComponent, List<SContainerQuoteForm> listSContainerQuoteForm)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        if (parentId < 1) {
            return null;
        }
        SiteContainer siteContainer = null;
        Iterator<SiteContainerParentData> iterator = listSiteContainerParentData.iterator();
        while (iterator.hasNext()) {
            SiteContainerParentData next = iterator.next();
            Iterator<SiteContainer> iteratorSiteContainer = next.getData().iterator();
            while (iteratorSiteContainer.hasNext()) {
                SiteContainer nextSiteContainer = iteratorSiteContainer.next();
                if (nextSiteContainer.getSContainer().getId().longValue() == parentId) {
                    siteContainer = nextSiteContainer;
                }
            }
        }
        /**
         * 只能 containerBox 才有后续的动作
         */
        if (siteContainer == null || siteContainer.getSContainer().getId() == null || siteContainer.getSContainer().getBoxId() == null
                || siteContainer.getSContainer().getTypeId().longValue() != 3) {
            return null;
        }

        SiteComponent siteComponent = getChildrenData(siteContainer, listSiteComponent);
        if (siteComponent != null) {
            // 获取 component 的HTML渲染内容
            SysComponentType componentType = null;
            try {
                componentType = sysStaticDataServiceImpl.getComponentTypeInfoById(siteComponent.getComponent().getTypeId());
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (componentType != null) {
                if (componentType.getCateType() != null && componentType.getCateType().shortValue() == (short) 2) {
                    HISystemComponentUdin systemComponentUdin = hIComponentUdinComponent.getHISystemComponentUdinByName(componentType.getType());
                    // 获取 SPage、SSystem 数据
                    SComponentQuoteSystem quoteSystem = siteComponent.getQuoteSystem();
                    if (systemComponentUdin != null && quoteSystem != null) {
                        Long quotePageId = quoteSystem.getQuotePageId();
                        Long quoteSystemId = quoteSystem.getQuoteSystemId();
                        Long quoteSystemCategoryId = quoteSystem.getQuoteSystemCategoryId();

                        SPage page = pageServiceImpl.getPageByHostPageId(siteComponent.getComponent().getHostId(), quotePageId);
                        SSystem system = systemServiceImpl.findInfo(siteComponent.getComponent().getHostId(), quoteSystemId);
                        SCategories categories = null;
                        if (quoteSystemCategoryId != null && quoteSystemCategoryId.longValue() > 0) {
                            categories = categoryServiceImpl.getInfoByHostCategoryId(siteComponent.getComponent().getHostId(), quoteSystemId,
                                    quoteSystemCategoryId);
                        }

                        List<StringBuilder> arrayList = new ArrayList<StringBuilder>();
                        arrayList.add(systemComponentUdin.html(page, system, categories, siteComponent));
                        return arrayList;
                    }
                } else {
                    HIComponentUdin componentUdin = hIComponentUdinComponent.getHIComponentUdinByName(componentType.getType());
                    if (componentUdin != null) {
                        List<StringBuilder> arrayList = new ArrayList<StringBuilder>();
                        arrayList.add(componentUdin.html(siteComponent));
                        return arrayList;
                    }
                }
            }
        }
        // 容器引用表单数据
        SContainerQuoteForm sContainerQuoteForm = getFormChildrenData(siteContainer, listSContainerQuoteForm);
        if (sContainerQuoteForm != null) {
            sRHeadServiceImpl.remakeform();
            StringBuilder html = hFormServiceImpl.html(sContainerQuoteForm);
            List<StringBuilder> arrayList = new ArrayList<StringBuilder>();
            arrayList.add(html);
            return arrayList;
        }
        return null;
    }

    /**
     * 通过参数验证并且获取 List<SiteComponent> listSiteComponent 数据列表中的 SiteComponent 数据
     *
     * @param siteContainer
     * @param listSiteComponent
     * @return
     */
    private static SiteComponent getChildrenData(SiteContainer siteContainer, List<SiteComponent> listSiteComponent) {
        if (CollectionUtils.isEmpty(listSiteComponent)) {
            return null;
        }
        Iterator<SiteComponent> iteratorSiteComponent = listSiteComponent.iterator();
        while (iteratorSiteComponent.hasNext()) {
            SiteComponent siteComponent = iteratorSiteComponent.next();
            Long containerId = siteComponent.getComponent().getContainerId();
            Long containerBoxId = siteComponent.getComponent().getContainerBoxId();
            if (containerId == null || containerBoxId == null) {
                return null;
            }

            if (siteContainer.getSContainer().getId().longValue() == containerId.longValue()
                    && siteContainer.getSContainer().getBoxId().longValue() == containerBoxId.longValue()) {
                return siteComponent;
            }
        }
        return null;
    }

    /**
     * 通过 parentId 找出对应的子项数据列表
     *
     * @param listSiteContainerParentData
     * @param parentId
     * @return
     */
    private static List<SiteContainer> getChildrenData(List<SiteContainerParentData> listSiteContainerParentData, long parentId) {
        if (CollectionUtils.isEmpty(listSiteContainerParentData)) {
            return null;
        }
        List<SiteContainer> listSiteContainer = null;
        Iterator<SiteContainerParentData> iterator = listSiteContainerParentData.iterator();
        while (iterator.hasNext()) {
            SiteContainerParentData siteContainerParentData = iterator.next();
            if (siteContainerParentData.getParentId() == parentId) {
                listSiteContainer = siteContainerParentData.getData();
            }
        }
        return listSiteContainer;
    }

    /**
     * 通过 参数 验证并且获取 List<SContainerQuoteForm> listSContainerQuoteForm 数据列表中对应的
     * SContainerQuoteForm 数据
     *
     * @param scontainerId
     * @param listSiteContainerParentData
     * @param listSContainerQuoteForm
     * @return
     */
    private static SContainerQuoteForm getFormChildrenData(SiteContainer siteContainer, List<SContainerQuoteForm> listSContainerQuoteForm) {
        if (CollectionUtils.isEmpty(listSContainerQuoteForm)) {
            return null;
        }
        Iterator<SContainerQuoteForm> iteratorSContainerQuoteForm = listSContainerQuoteForm.iterator();
        while (iteratorSContainerQuoteForm.hasNext()) {
            SContainerQuoteForm sContainerQuoteForm = iteratorSContainerQuoteForm.next();
            if (sContainerQuoteForm.getContainerId().longValue() == siteContainer.getSContainer().getId().longValue()) {
                return sContainerQuoteForm;
            }
        }
        return null;
    }

    @Data
    @Accessors(chain = true)
    @ToString
    public static class SiteContainerParentData {
        private long parentId;
        private List<SiteContainer> data;

        public static List<SiteContainerParentData> getListSiteContainerParentData(List<SiteContainer> listSiteContainer) {
            if (CollectionUtils.isEmpty(listSiteContainer)) {
                return null;
            }
            List<SiteContainerParentData> listSiteContainerParentData = new ArrayList<HSpublicServiceImpl.SiteContainerParentData>();

            Iterator<SiteContainer> iterator = listSiteContainer.iterator();
            while (iterator.hasNext()) {
                SiteContainer next = iterator.next();
                long parentId = next.getSContainer().getParentId() == null ? 0 : next.getSContainer().getParentId().longValue();

                // 是否存在
                SiteContainerParentData item = null;
                Iterator<SiteContainerParentData> iteratorSiteContainerParentData = listSiteContainerParentData.iterator();
                while (iteratorSiteContainerParentData.hasNext()) {
                    SiteContainerParentData siteContainerParentData = iteratorSiteContainerParentData.next();
                    if (siteContainerParentData.getParentId() == parentId) {
                        item = siteContainerParentData;
                        break;
                    }
                }

                if (item == null) {
                    item = new SiteContainerParentData();
                    item.setParentId(parentId);
                    item.setData(new ArrayList<>());
                    listSiteContainerParentData.add(item);
                }

                item.getData().add(next);
            }

            return listSiteContainerParentData;
        }
    }

}
